package AneRouge;
import java.util.Random;
import java.util.Vector;

public class AneRougeBoard {

	final static int empty = -2;

	final static int wall = -1;

	final static int numBloc = 10;

	final static int blocDX[] = { 1, 2, 1, 1, 2, 1, 1, 1, 1, 1 };

	final static int blocDY[] = { 2, 2, 2, 2, 1, 2, 1, 1, 1, 1 };

	final static int type[] = { 1, 2, 1, 1, 3, 1, 0, 0, 0, 0 };

	// Vector hashVec[]= new Vector[3];

	final static int blocIPX[] = { 1, 2, 4, 1, 2, 4, 2, 3, 1, 4 };

	final static int blocIPY[] = { 1, 1, 1, 3, 3, 3, 4, 4, 5, 5 };

	final static int dirX[] = { -1, 0, 1, 0 };

	final static int dirY[] = { 0, 1, 0, -1 };

	int board[][];

	int blocPX[], blocPY[];

	long hashValues[][][];

	AneRougeBoard() {

		board = new int[4 + 2][5 + 2];
		hashValues = new long[4][4 + 2][5 + 2];
		Random r = new Random();

		for (int t = 0; t < 4; t++) {
			for (int i = 0; i < 6; i++) {
				for (int j = 0; j < 7; j++) {
					hashValues[t][i][j] = r.nextLong();
				}
			}
		}
		blocPX = new int[numBloc];
		blocPY = new int[numBloc];
		reset();
	}

	public long longHashCode() {
		long hash = 0; 
		for (int i=0;i<numBloc;i++) {
			int t=type[i];
			hash = hash ^ hashValues[t][blocPX[i]][blocPY[i]];
		}
		return hash;
		
	}
//
//	long hashCode1() {
//		boolean[] done = new boolean[numBloc];
//		for (int i = 0; i < 6; i++) {
//			for (int j = 0; j < 7; j++) {
//				int b = board[i][j];
//				if (b >= 0) {
//					if (!done[b]) {
//						System.out.println((i - 1) + " " + (j - 1) + " " + b
//								+ " " + type[b]);
//						done[b] = true;
//					}
//				}
//			}
//		}
//		return 0;
//
//	}

	public boolean canMove(int n, int dir) {
		boolean can = true;
		assert (n >= 0 && n < numBloc);
		if (dir >= 0 && dir < 4)
			can = isClear(n, blocPX[n] + dirX[dir], blocPY[n] + dirY[dir],
					blocDX[n], blocDY[n]);
		// System.out.println(" can move " + n + " " + dir + " " + can);
		return can;
	}

	private void clearBoard() {
		for (int i = 0; i < 6; i++)
			for (int j = 0; j < 7; j++)
				if (i == 0 || i == 5 || j == 0 || j == 6)
					board[i][j] = wall;
				else
					board[i][j] = empty;
	}

	void eraseBloc(int n) {
		for (int i = 0; i < blocDX[n]; i++)
			for (int j = 0; j < blocDY[n]; j++)
				board[blocPX[n] + i][blocPY[n] + j] = empty;
	}

	private boolean isClear(int movingBloc, int px, int py, int dx, int dy) {
		boolean clear = true;
		for (int i = 0; i < dx && clear; i++)
			for (int j = 0; j < dy && clear; j++)
				if (board[px + i][py + j] != empty
						&& board[px + i][py + j] != movingBloc)
					clear = false;
		return clear;
	}

	void reset() {
		clearBoard();
		for (int n = 0; n < numBloc; n++) {
			blocPX[n] = blocIPX[n];
			blocPY[n] = blocIPY[n];

			for (int i = 0; i < blocDX[n]; i++)
				for (int j = 0; j < blocDY[n]; j++)
					board[i + blocPX[n]][j + blocPY[n]] = n;
		}

	}

	public void moveBloc(int n, int dir) {
		eraseBloc(n);
		moveBlocBy(n, dirX[dir], dirY[dir]);
	}

	private void moveBlocBy(int n, int dx, int dy) {
		blocPX[n] += dx;
		blocPY[n] += dy;

		for (int i = 0; i < blocDX[n]; i++) {
			for (int j = 0; j < blocDY[n]; j++) {
				board[i + blocPX[n]][j + blocPY[n]] = n;
			}
		}
	}

	boolean hasWon() {
		return blocPX[1] == 2 && blocPY[1] == 4;
	}

	public void unMoveBloc(int block, int dir) {
		moveBloc(block, (dir+2)%4 );
	}

}
